//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "cmutex.h"
#include "helper.h"
#include <aura.h>

CMutex::~CMutex()
{
    if (NULL != m_hMutex) {
        AuraMutex_Destroy(m_hMutex);
        m_hMutex = NULL;
    }
}

ECode CMutex::Constructor()
{
    return AuraMutex_Create(&m_hMutex);
}

PInterface CMutex::Probe(
    /* [in]  */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (PInterface)(IMutex *)this;
    }
    else if (riid == EIID_IMutex) {
        return (IMutex *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CMutex;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface)&EIID_IMutex;
    }

    return NULL;
}

UInt32 CMutex::AddRef()
{
    Int32 nRefs = m_nRefs.Increment();

    return (UInt32)nRefs;
}

UInt32 CMutex::Release()
{
    Int32 nRefs = m_nRefs.Decrement();

    if (nRefs == 0) {
        delete this;
    }
    return (UInt32)nRefs;
}

ECode CMutex::Aggregate(
    /* [in]  */ AggrType type,
    /* [in]  */ PInterface pObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CMutex::GetDomain(
    /* [out] */ PInterface * ppObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CMutex::Lock(
    /* [out] */ WaitResult * pResult)
{
    ECode ec = NOERROR;

    if (NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    THREAD_START_SLEEP()
    {
        ec = AuraMutex_Lock(m_hMutex,
                    (Aura_Millisecond32)INFINITE,
                    (Aura_WaitResult *)pResult);
    }
    THREAD_END_SLEEP;

    return ec;
}

ECode CMutex::TryLock(
    /* [in]  */ Millisecond32 msTimeout,
    /* [out] */ WaitResult * pResult)
{
    ECode ec = NOERROR;

    if (NULL == pResult) {
        return E_INVALID_ARGUMENT;
    }

    THREAD_START_SLEEP()
    {
        ec = AuraMutex_Lock(m_hMutex,
                    (Aura_Millisecond32)msTimeout,
                    (Aura_WaitResult *)pResult);
    }
    THREAD_END_SLEEP;

    return ec;
}

ECode CMutex::Unlock()
{
    return AuraMutex_Unlock(m_hMutex);
}


ECode CMutex::New(
    /* [out] */ IMutex ** ppMutex)
{
    CMutex * pMutex = NULL;
    ECode ec = NOERROR;

    assert(NULL != ppMutex);

    pMutex = new CMutex();
    if (NULL == pMutex) {
        ec = E_OUT_OF_MEMORY;
        goto E_FAIL_EXIT;
    }
    ec = pMutex->Constructor();
    if (FAILED(ec)) {
        goto E_FAIL_EXIT;
    }
    *ppMutex = static_cast<IMutex*>(pMutex);
    (*ppMutex)->AddRef();

    return NOERROR;

E_FAIL_EXIT:
    if (NULL != pMutex) {
        delete pMutex;
    }
    return ec;
}

